<?php
/**
 * Created by PhpStorm.
 * User: tom_xia
 * Date: 2018/8/9
 * Time: 14:04
 * 用户相关 处理
 */
namespace app\service;
use app\cls\tom\Encrypt;
use app\cls\tom\RedisKeyFactory;
use app\cls\tom\Response;
use app\cls\tom\SysResource;
use app\cls\tom\Tools;
use app\model\Users;

class User{

    private static $key = "123456000";
    private $tokenVersion = "1.0";

    //获取用户信息
    public function getUserInfo($userUUID)
    {
        $userKey = REDIS_PREFIX."one_user_info_".$userUUID;
        $redis = SysResource::getRedis();
        $userInfo = $redis->get($userKey);
        if(false){
            $userInfo = json_decode($userInfo,true);
        }else{
            $db = SysResource::getDB(false);
            $userModel = new Users($db);
            $userModel->setDb($db);

            $userInfo = $userModel->getUserInfo($userUUID);
            $redis->setex($userKey,60,json_encode($userInfo));
        }
        return $userInfo;
    }

    /**
     * @return string
     */
    public function getUserUUIDByHTPPHeaderToken()
    {
        $token = isset($_SERVER["HTTP_AUTH_TOKEN"]) ? $_SERVER["HTTP_AUTH_TOKEN"] : "";
        $userUUID = "";
        if($token){
            $uInfo = $this->validateToken($token);
            if(!($uInfo instanceof Response)){
                $userUUID = $uInfo["uuid"];
            }
        }
        return $userUUID;
    }

    /**
     * 验证客户端token是否有效
     * @param $token
     * @param bool $isExpandExpireTime 是否延长时间
     * @return Response|array
     */
    public function validateToken($token,$isExpandExpireTime = true)
    {
        $info = $this->decryptToken($token);
        if(empty($info)){
            return new Response(-1001,"无效的token");
        }
        $unionId = $info["uuid"];
        $redis = SysResource::getRedis();
        $userKey = RedisKeyFactory::getUserTokenKey($unionId);
        $u_info = $redis->get($userKey);
        if(empty($u_info)){
            return new Response(-1001,"用户没有登录或者token已经过期!");
        }
        $u_info = json_decode($u_info,true);
        //校验用户是否被冻结
        if(isset($u_info["frozen"]) && $u_info["frozen"] == 1){
            return new Response(-1001, "用户已经被冻结");
        }
        if($isExpandExpireTime){
            $ttl = $redis->ttl($userKey);
            if($ttl >= 0 && $ttl < 7200){
                //延长时间
                $redis->expire($userKey,365*86400);
            }
        }
        return ["login_time"=>$info["login_time"]] + $u_info;
    }

    /**
     * 解码token
     * @param $token
     * @return array | string
     */
    public function decryptToken($token)
    {
        $decryptValue = Encrypt::decode($token);
        $val = explode("_", $decryptValue);
        if (count($val) != 3) {
            return "";
        }
        $serializeInfo = substr($val[0], 4);
        if (md5($serializeInfo . "|" . $val[1] . static::$key) != $val[2]) {
            return "";
        }
        return unserialize(base64_decode($serializeInfo));
    }


    /**
     * 加密id为token
     * @param $encryptInfo
     * @return mixed
     */
    public function encryptToken(array $encryptInfo)
    {
        $encryptInfo["token_version"] = $this->tokenVersion;
        $time = intval(microtime(true)*1000);
        $serializeInfo = base64_encode(serialize($encryptInfo));
        $encryptValue = rand(1000, 9999) . $serializeInfo . "_" . $time . "_" . md5($serializeInfo . "|" . $time . static::$key);
        $token = Encrypt::encode($encryptValue);
        return $token;
    }

    /**
     * 用户登录
     * @param array $userInfo
     * @return Response
     */
    public function login(array $userInfo)
    {
//        var_dump($userInfo);exit;
        $openId = $userInfo["open_id"];
        $db = SysResource::getDB(true);
        $userModel = new Users($db);
        $info = $userModel->getInfo(["third_uuid"=>$openId]);
        if(empty($info)){
            $uuid = Tools::UUID();
            $time = date("Y-m-d H:i:s");
//            var_dump($userInfo);exit;
            $userModel->save("add",["uuid"=>$uuid,
                "third_uuid"=>$openId,"nick_name"=>$userInfo["nickName"],
                "nick_pic"=>$userInfo["avatarUrl"],"add_time"=>$time]);

            $newUserInfo = array();
            $newUserInfo["uuid"] = $uuid;
            $newUserInfo["nick_name"] = $userInfo["nickName"];
            $newUserInfo["nick_pic"] = $userInfo["avatarUrl"];
            $newUserInfo["add_time"] = $time;
            $newUserInfo["frozen"] = 2;

            $tokenInfo = ["login_time"=>date("Y-m-d H:i:s"),"uuid"=>$uuid];
            $newUserInfo["token"] = $this->encryptToken($tokenInfo) ;
        }else{
            $newUserInfo = array();
//            $userModel->save("update",["nick_name"=>$userInfo["nickName"],"nick_pic"=>$userInfo["avatarUrl"],['uuid'=>$info]]);
            $newUserInfo["uuid"] = $info["uuid"];
            $newUserInfo["nick_name"] = $info["nick_name"];
            $newUserInfo["nick_pic"] = $info["nick_pic"];
            $newUserInfo["add_time"] = $info["add_time"];
            $newUserInfo["frozen"] = $info["status"];

            $tokenInfo = ["login_time"=>date("Y-m-d H:i:s"),"uuid"=>$info["uuid"]];
            $newUserInfo["token"] = $this->encryptToken($tokenInfo) ;
        }
        $this->saveTokenToRedis($newUserInfo["uuid"],$newUserInfo,1);
        return new Response(0,"登录成功",$newUserInfo);
    }
    //利用三方uuid生成token
    public function create_token($openId)
    {
        $db = SysResource::getDB(false);
        $userModel = new Users($db);
        $info = $userModel->getInfo(["third_uuid"=>$openId]);
        if(empty($info)){
            return new Response(-1,"登录失败");
        }else{
            $newUserInfo = array();
            $newUserInfo["uuid"] = $info["uuid"];
            $newUserInfo["nick_name"] = $info["nick_name"];
            $newUserInfo["nick_pic"] = $info["nick_pic"];
            $newUserInfo["add_time"] = $info["add_time"];
            $newUserInfo["frozen"] = $info["status"];

            $tokenInfo = ["login_time"=>date("Y-m-d H:i:s"),"uuid"=>$info["uuid"]];
            $newUserInfo["token"] = $this->encryptToken($tokenInfo) ;
            $this->saveTokenToRedis($newUserInfo["uuid"],$newUserInfo,1);
            return new Response(0,"登录成功",$newUserInfo);
        }

    }

    /**
     * @param $unionId
     * @param array $saveInfo
     * @param int $autoLogin
     */
    private function saveTokenToRedis($unionId, array $saveInfo,$autoLogin = 0)
    {
        $expireIn = $autoLogin ? 365*86400 : 7200;
        $key = RedisKeyFactory::getUserTokenKey($unionId);
        $redis = SysResource::getRedis();
        $redis->setEx($key, $expireIn,json_encode($saveInfo));
    }
}